package tl;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.tree.CommonTree;

import tplenguajes.TLexer;
import tplenguajes.TParser;
import tplenguajes.TParser.s_return;
import tplenguajes.grafo.AFD;
import tplenguajes.grafo.AFND;

public class RegexEngine {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		if (args.length < 2){ //Se tiene que recibir dos parámetros
			System.err.println("Uso: RegexEngine 'regex' archivo.txt");
			System.exit(1);
		}
	
		TLexer lexer = new TLexer();
		AFD<String> automaton = null;

		//Se parsea la expresión regular recibida
		try{
			automaton = parseRegex(args[0], lexer);
		}catch(Exception e){
			System.err.println("ERROR: La expresión regular ingresada '" + args[0] + "' no es válida.");
			System.exit(1);
		}
		
		try{
			FileInputStream fstream	= new FileInputStream(args[1]);
			DataInputStream in 		= new DataInputStream(fstream);
			BufferedReader  br 		= new BufferedReader(new InputStreamReader(in));
			String strLine;
			//Se lee el archivo línea por línea
			while ((strLine = br.readLine()) != null)   {
				// Imprime todas las líneas por Standard Output
				//System.out.println ("XXXXX: " + strLine);
				Iterable<String> iterableString = getIterableString(strLine);
				if (automaton.acceptsString(iterableString))
					System.out.println(strLine);
			}
		}catch (IOException e) {
			System.err.println("ERROR: Hubo un problema al intentar abrir el archivo de texto ("+ e + ").");
			e.printStackTrace();
		}catch (Exception e){
			System.err.println("ERROR: Hubo un problema desconocido (" + e + ").");
			e.printStackTrace();
		}		
	}

	public static AFD<String> parseRegex(String source, TLexer lexer) throws Exception {
			//Parseando regex
			lexer.setCharStream(new ANTLRStringStream(source));

			CommonTokenStream tokens = new CommonTokenStream(lexer);

			TParser parser = new TParser(tokens);
			s_return psrReturn = parser.s();

			CommonTree t = (CommonTree) psrReturn.getTree();

			// Se define el alfabeto
			Set<String> alphabet = new HashSet<String>();
			for (char c = 'a'; c < 'z' + 1; c++)
				alphabet.add(Character.toString(c));
			for (char c = 'A'; c < 'Z' + 1; c++)
				alphabet.add(Character.toString(c));
			for (char c = '0'; c < '9' + 1; c++)
				alphabet.add(Character.toString(c));
			alphabet.add(" ");

			//System.out.println("Alfabeto:" + alphabet);
			
			//Generando AFND
			AFND<String> afnd = new AFND<String>(t, alphabet);
			//Convirtiendo a AFD
			AFD<String> afd = new AFD<String>(afnd);
			
			return afd; 
	}

	public static void printTree(CommonTree t, int indent) {
		if (t != null) {
			StringBuffer sb = new StringBuffer(indent);
			for (int i = 0; i < indent; i++)
				sb = sb.append("   ");
			for (int i = 0; i < t.getChildCount(); i++) {
				System.out.println(sb.toString() + t.getChild(i).toString()
						+ "  " + t.getChild(i).getChildCount());
				printTree((CommonTree) t.getChild(i), indent + 1);
			}
		}
	}
	
	private static List<String> getIterableString(String string){
		List<String> iterableString = new ArrayList<String>();
		
		for(int i=0; i<string.length(); i++){
			iterableString.add(string.substring(i, i+1));
		}
		
		return iterableString;
	}
	
}
